package com.xindacloud.sms.portal.controller;

import com.xindacloud.sms.portal.dto.SearchMessageDTO;
import com.xindacloud.sms.portal.dto.SubmitMessageDTO;
import com.xindacloud.sms.portal.exception.ServiceException;
import com.xindacloud.sms.portal.properties.EndpointProperties;
import com.xindacloud.sms.portal.service.ISmsSubmissionRecordService;
import com.xindacloud.sms.portal.utils.ImportRecipientUtil;
import com.xindacloud.sms.portal.utils.UnionResultHelp;
import com.xindacloud.sms.portal.utils.UserSessionHelp;
import com.xindacloud.sms.portal.vo.SearchMessageVO;
import com.xindacloud.sms.portal.vo.ValidNumberResultVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;

import static com.xindacloud.sms.portal.utils.UserSessionHelp.getUserFromSession;

@Api(tags = {"短信发送接口"})
@RestController
@RequestMapping(value = "/api/v1/portal/sms")
@Slf4j
public class SubmitMessageController {

    private final EndpointProperties endpointProperties;

    final ISmsSubmissionRecordService smsSubmissionRecordService;

    final ExecutorService executorService;

    @Autowired
    public SubmitMessageController(EndpointProperties endpointProperties, ISmsSubmissionRecordService smsSubmissionRecordService, ExecutorService executorService) {

        this.endpointProperties = endpointProperties;
        this.smsSubmissionRecordService = smsSubmissionRecordService;
        this.executorService = executorService;
    }

    @ApiOperation(value = "发送短信", response = UnionResultHelp.class)
    @PostMapping(value = "/send", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public UnionResultHelp submitMessage(@ApiParam(name = "submitMessageDTO", value = "发送短信", required = true)
                                         @RequestBody @Valid SubmitMessageDTO submitMessageDTO,
                                         HttpServletRequest request) {


        String url = endpointProperties.getAdapterGateway().concat(endpointProperties.getAdapterSubmitPath());
        try {
            CompletableFuture.runAsync(() -> WebClient
                    .create(url)
                    .post()
                    .accept(MediaType.APPLICATION_JSON)
                    .headers(UserSessionHelp.getHttpHeadersConsumer(request))
                    .body(Mono.just(submitMessageDTO), SubmitMessageDTO.class)
                    .retrieve()
                    //.onErrorReturn()
                    .onStatus(HttpStatus::is4xxClientError, clientResponse ->
                            Mono.error(new ServiceException("发送短信异常.", clientResponse.statusCode().value()))
                    )
                    .onStatus(HttpStatus::is5xxServerError, clientResponse ->
                            Mono.error(new ServiceException("发送短信异常.", clientResponse.statusCode().value()))
                    )
                    .bodyToMono(new ParameterizedTypeReference<UnionResultHelp>() {
                    })
                    .block(), executorService);
        } catch (Exception e) {
            return new UnionResultHelp<>(UnionResultHelp.StatusEnum.Fail, "提交短信异常.");
        }
        return new UnionResultHelp<>(UnionResultHelp.StatusEnum.Success, "提交短信成功.");
    }

    @ApiOperation(value = "查询短信", response = SearchMessageVO.class)
    @PostMapping(value = "/search", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public Object searchMessage(@ApiParam(name = "searchMessageDTO", value = "查询短信", required = true)
                                @RequestBody @Valid SearchMessageDTO searchMessageDTO,
                                HttpServletRequest request) {

        searchMessageDTO.setUserId(getUserFromSession(request).getUserId().toString());
        return smsSubmissionRecordService.searchMessage(searchMessageDTO);
    }


    @ApiOperation(value = "群发导入号码支持格式为csv,excel", notes = "返回200为修改成功,其他返回码均为异常")
    @PostMapping(value = "/import-recipient")
    public Object importRecipient(@ApiParam(name = "file", value = "群发导入号码,支持格式为csv,excel", required = true)
                                  @RequestParam("file") MultipartFile file, HttpServletRequest request) {
        final List<String> recipients = ImportRecipientUtil.importRecipient(file);
        final HashSet<String> recipientHashSet = new HashSet<>(recipients);
        return ValidNumberResultVO.builder()
                .isValidNumber(false)
                .invalidRecipientList(Collections.emptyList())
                .invalidCount(0)
                .validRecipientList(new ArrayList<>(recipientHashSet))
                .validCount(recipientHashSet.size())
                .totalCount(recipients.size())
                .build();
       /* String url = endpointProperties.getAdapterGateway().concat(endpointProperties.getAdapterValidNumberPath());
        final UnionResultHelp unionResultHelp = WebClient
                .create(url)
                .post()
                .accept(MediaType.APPLICATION_JSON)
                .headers(UserSessionHelp.getHttpHeadersConsumer(request))
                .body(Mono.just(ValidNumberParamDTO.builder().recipientList(recipients).build()), ValidNumberParamDTO.class)
                .retrieve()
                .onStatus(HttpStatus::is4xxClientError, clientResponse ->
                        Mono.error(new ServiceException("号码检验异常.", clientResponse.statusCode().value()))
                )
                .onStatus(HttpStatus::is5xxServerError, clientResponse ->
                        Mono.error(new ServiceException("号码检验异常.", clientResponse.statusCode().value()))
                )
                .bodyToMono(new ParameterizedTypeReference<UnionResultHelp>() {
                })
                .block();
        final Object data = unionResultHelp.getData();
        if (Objects.nonNull(data)) {
            final Gson gson = new Gson();
            final List<String> invalidRecipientList = gson.fromJson(gson.toJson(data), List.class);
            final List<String> validRecipientList = recipients.stream()
                    .filter(rs -> !invalidRecipientList.contains(rs))
                    .collect(Collectors.toList());
            return ValidNumberResultVO.builder()
                    .isValidNumber(false)
                    .invalidRecipientList(invalidRecipientList)
                    .invalidCount(invalidRecipientList.size())
                    .validRecipientList(validRecipientList)
                    .validCount(validRecipientList.size())
                    .totalCount(recipients.size())
                    .build();
        } else {
            return ValidNumberResultVO.builder()
                    .isValidNumber(true)
                    .invalidRecipientList(Collections.EMPTY_LIST)
                    .invalidCount(0)
                    .validRecipientList(recipients)
                    .validCount(recipients.size())
                    .totalCount(recipients.size())
                    .build();
        }*/

    }


    private HttpEntity<?> setHttpEntity(Object object, String token, String password) {
        HttpHeaders headers = setHttpHeaders(token, password);
        return new HttpEntity<>(object, headers);
    }

    private HttpHeaders setHttpHeaders(String token, String password) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        headers.set("token", token);
        headers.set("password", password);
        return headers;
    }
}
